var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var _this = this;
var ao;
(function (ao) {
    var constants = (function () {
        function constants() {
        }
        constants.keyDataContext = "dataContext";
        return constants;
    })();
    ao.constants = constants;

    var DependencyProperty = (function () {
        function DependencyProperty(name, propertyType, ownerType, propertyMetadata) {
            this._name = name;
            this._propertyType = propertyType;
            this._ownerType = ownerType;
            this._propertyMetadata = propertyMetadata;
        }
        Object.defineProperty(DependencyProperty.prototype, "Name", {
            get: function () {
                return this._name;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(DependencyProperty.prototype, "PropertyType", {
            get: function () {
                return this._propertyType;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(DependencyProperty.prototype, "OwnerType", {
            get: function () {
                return this._ownerType;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(DependencyProperty.prototype, "DefaultMetadata", {
            get: function () {
                return this._propertyMetadata;
            },
            enumerable: true,
            configurable: true
        });

        DependencyProperty.Register = function (name, propertyType, ownerType, typeMetadata, validateValueCallback) {
            var dependencyProperty = new DependencyProperty(name, propertyType, ownerType, typeMetadata);

            DependencyProperty.DependencyProperties[name] = dependencyProperty;
            DependencyProperty.DefineDependencyProperty(name, dependencyProperty);
            DependencyProperty.DefineDPSourceElement(name);
            return dependencyProperty;
        };

        DependencyProperty.DefineDependencyProperty = function (propertyName, dp) {
            var innerProprtyName = '_' + propertyName;
            Object.defineProperty(Element.prototype, propertyName, {
                get: function () {
                    var objValue = this[innerProprtyName];
                    if (objValue === undefined && this.parentElement !== undefined && this.nodeName != "BODY") {
                        return this.parentElement[propertyName];
                    }
                    return this[innerProprtyName];
                },
                set: function (value) {
                    var oldValue = this[innerProprtyName];
                    this[innerProprtyName] = value;

                    var changedCallback = dp.DefaultMetadata.GetPropertyChangedCallback;
                    if (changedCallback != null) {
                        if (oldValue != value) {
                            var param = new DependencyPropertyChangedEventArgs(dp, oldValue, value);
                            changedCallback(this, param);
                        }
                    }
                }
            });
        };

        DependencyProperty.DefineDPSourceElement = function (propertyName) {
            var innerProprtyName = '_' + propertyName;

            Object.defineProperty(Element.prototype, propertyName + 'SourceElement', {
                get: function () {
                    return DependencyProperty.getParentSource(innerProprtyName, this);
                }
            });
        };

        DependencyProperty.getParentSource = function (propertyName, element) {
            if (element[propertyName] == null && element.nodeName != "BODY") {
                return DependencyProperty.getParentSource(propertyName, element.parentElement);
            } else {
                return element;
            }
        };
        return DependencyProperty;
    })();
    ao.DependencyProperty = DependencyProperty;

    var PropertyMetadata = (function () {
        function PropertyMetadata(defaultValue, propertyChangedCallback, coerceValueCallback) {
            this._propertyChangedCallback = propertyChangedCallback;
            this._coerceValueCallback = coerceValueCallback;
        }
        Object.defineProperty(PropertyMetadata.prototype, "GetPropertyChangedCallback", {
            get: function () {
                return this._propertyChangedCallback;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(PropertyMetadata.prototype, "GetCoerceValueCallback", {
            get: function () {
                return this._coerceValueCallback;
            },
            enumerable: true,
            configurable: true
        });
        return PropertyMetadata;
    })();
    ao.PropertyMetadata = PropertyMetadata;

    var DependencyPropertyChangedEventArgs = (function () {
        function DependencyPropertyChangedEventArgs(property, oldValue, newValue) {
            this._property = property;
            this._oldValue = oldValue;
            this._newValue = newValue;
        }
        Object.defineProperty(DependencyPropertyChangedEventArgs.prototype, "property", {
            get: function () {
                return this._property;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(DependencyPropertyChangedEventArgs.prototype, "newValue", {
            get: function () {
                return this._newValue;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(DependencyPropertyChangedEventArgs.prototype, "oldValue", {
            get: function () {
                return this._oldValue;
            },
            enumerable: true,
            configurable: true
        });
        return DependencyPropertyChangedEventArgs;
    })();
    ao.DependencyPropertyChangedEventArgs = DependencyPropertyChangedEventArgs;

    var BindingOperations = (function () {
        function BindingOperations() {
        }
        BindingOperations.GetBindingExpression = function (target/*DependencyObject*/ , dp) {
            return null;
        };

        BindingOperations.SetBinding = function (target/*DependencyObject*/ , dp, binding) {
            var bindingExpression = new BindingExpression(target, dp, binding);

            return bindingExpression;
        };
        return BindingOperations;
    })();
    ao.BindingOperations = BindingOperations;

    var HtmlServiceProvider = (function () {
        function HtmlServiceProvider() {
        }
        HtmlServiceProvider.prototype.GetService = function (serviceType) {
            var obj = {};
            obj['TargetProperty'] = this.TargetProperty;
            obj['TargetObject'] = this.TargetObject;
            return obj;
        };
        return HtmlServiceProvider;
    })();
    ao.HtmlServiceProvider = HtmlServiceProvider;

    var BindingExpressionBase = (function () {
        function BindingExpressionBase(target, targetProperty) {
            this._target = target;
            this._targetProperty = targetProperty;
        }
        Object.defineProperty(BindingExpressionBase.prototype, "Target", {
            get: function () {
                return this._target;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(BindingExpressionBase.prototype, "TargetProperty", {
            get: function () {
                return this._targetProperty;
            },
            enumerable: true,
            configurable: true
        });

        BindingExpressionBase.prototype.UpdateSource = function () {
        };

        BindingExpressionBase.prototype.UpdateTarget = function () {
        };
        return BindingExpressionBase;
    })();
    ao.BindingExpressionBase = BindingExpressionBase;

    var BindingExpression = (function (_super) {
        __extends(BindingExpression, _super);
        function BindingExpression(target, targetProperty, binding) {
            var _this = this;
            _super.call(this, target, targetProperty);
            this._binding = binding;

            if (this.Target instanceof HTMLInputElement) {
                var inputElement = this.Target;

                var listener = function (event) {
                    _this.UpdateSource();
                };
                inputElement.addEventListener("blur", listener);
            }

            var targetSourceElement = this.getSourceElement();

            if (targetSourceElement != null) {
                targetSourceElement.onChangeNotify.addEvent(function () {
                    _this.UpdateTarget();
                });
            }
        }
        Object.defineProperty(BindingExpression.prototype, "DataItem", {
            get: function () {
                return null;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(BindingExpression.prototype, "ParentBinding", {
            get: function () {
                return this._binding;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(BindingExpression.prototype, "ResolvedSource", {
            get: function () {
                return null;
            },
            enumerable: true,
            configurable: true
        });

        Object.defineProperty(BindingExpression.prototype, "ResolvedSourcePropertyName", {
            get: function () {
                return null;
            },
            enumerable: true,
            configurable: true
        });

        BindingExpression.prototype.UpdateSource = function () {
            var binding = this.ParentBinding;
            var source = this.getSource();
            if (source == null) {
                return;
            }
            if (this.Target instanceof HTMLInputElement) {
                var inputElement = this.Target;
                source[binding.Path] = inputElement.value;
            }
        };

        BindingExpression.prototype.UpdateTarget = function () {
            var binding = this.ParentBinding;
            var source = this.getSource();
            var value = source != null ? source[binding.Path] : '';

            if (this.Target instanceof HTMLInputElement) {
                var inputElement = this.Target;
                inputElement.value = value;
            } else {
                this.Target.innerHTML = value;
            }
        };

        BindingExpression.prototype.getSource = function () {
            var binding = this.ParentBinding;
            var source = binding.Source;
            if (source == null) {
                return this.Target['dataContext'];
            }
            return null;
        };

        BindingExpression.prototype.getSourceElement = function () {
            var binding = this.ParentBinding;
            var source = binding.Source;
            if (source == null) {
                return this.Target['dataContextSourceElement'];
            } else {
                return this.Target;
            }
        };
        return BindingExpression;
    })(BindingExpressionBase);
    ao.BindingExpression = BindingExpression;

    //-------------
    var MarkupExtension = (function () {
        function MarkupExtension() {
        }
        Object.defineProperty(MarkupExtension.prototype, "Name", {
            get: function () {
                return this._name;
            },
            set: function (value) {
                this._name = value;
            },
            enumerable: true,
            configurable: true
        });


        MarkupExtension.prototype.provideValue = function (serviceProvider) {
            return null;
        };

        MarkupExtension.register = function (name, markupExtension) {
            markupExtension.Name = name;
            MarkupExtension.MarkupExtensions[name] = markupExtension;
        };
        return MarkupExtension;
    })();
    ao.MarkupExtension = MarkupExtension;

    var BindingBase = (function (_super) {
        __extends(BindingBase, _super);
        function BindingBase() {
            _super.apply(this, arguments);
        }
        Object.defineProperty(BindingBase.prototype, "StringFormat", {
            get: function () {
                return this._stringFormat;
            },
            set: function (value) {
                this._stringFormat = value;
            },
            enumerable: true,
            configurable: true
        });

        return BindingBase;
    })(MarkupExtension);
    ao.BindingBase = BindingBase;

    var anonymousProperty = "anonymous";

    var Binding = (function (_super) {
        __extends(Binding, _super);
        function Binding() {
            _super.apply(this, arguments);
        }
        Binding.prototype.provideValue = function (serviceProvider) {
            var valueProvider = serviceProvider.GetService("");

            if (valueProvider == null) {
                return null;
            }

            var bindingTarget = valueProvider['TargetObject'];
            var bindingProperty = valueProvider['TargetProperty'];

            return BindingOperations.SetBinding(bindingTarget, bindingProperty, this);
        };

        Object.defineProperty(Binding.prototype, "Path", {
            get: function () {
                if (this["path"] == undefined) {
                    return this[anonymousProperty + "_0"];
                }
                return this["path"];
            },
            enumerable: true,
            configurable: true
        });
        return Binding;
    })(BindingBase);
    ao.Binding = Binding;

    var StaticResourceExtension = (function (_super) {
        __extends(StaticResourceExtension, _super);
        function StaticResourceExtension() {
            _super.apply(this, arguments);
        }
        Object.defineProperty(StaticResourceExtension.prototype, "ResourceKey", {
            get: function () {
                return this._resourceKey;
            },
            set: function (value) {
                this._resourceKey = value;
            },
            enumerable: true,
            configurable: true
        });


        StaticResourceExtension.prototype.provideValue = function (serviceProvider) {
            return null;
        };
        return StaticResourceExtension;
    })(MarkupExtension);
    ao.StaticResourceExtension = StaticResourceExtension;

    var RelativeSourceExtension = (function (_super) {
        __extends(RelativeSourceExtension, _super);
        function RelativeSourceExtension() {
            _super.apply(this, arguments);
        }
        RelativeSourceExtension.prototype.provideValue = function (serviceProvider) {
            return null;
        };
        return RelativeSourceExtension;
    })(MarkupExtension);
    ao.RelativeSourceExtension = RelativeSourceExtension;

    var DynamicResourceExtension = (function (_super) {
        __extends(DynamicResourceExtension, _super);
        function DynamicResourceExtension() {
            _super.apply(this, arguments);
        }
        Object.defineProperty(DynamicResourceExtension.prototype, "ResourceKey", {
            get: function () {
                return this._resourceKey;
            },
            set: function (value) {
                this._resourceKey = value;
            },
            enumerable: true,
            configurable: true
        });
        DynamicResourceExtension.prototype.provideValue = function (serviceProvider) {
            return null;
        };
        return DynamicResourceExtension;
    })(MarkupExtension);
    ao.DynamicResourceExtension = DynamicResourceExtension;

    var HtmlMarkup = (function () {
        function HtmlMarkup() {
        }
        HtmlMarkup.bind = function () {
            var rootElement = document.getElementsByTagName("body")[0];
            rootElement['dataContext'] = {};
            HtmlMarkup.bindInternal(rootElement);
        };

        HtmlMarkup.bindInternal = function (element) {
            if (element instanceof HTMLElement) {
                HtmlMarkup.applyBindingToControl(element);
                for (var i in element.children) {
                    var childElement = element.children[i];
                    HtmlMarkup.bindInternal(childElement);
                }
            }
        };

        HtmlMarkup.applyBindingToControl = function (element) {
            if (element == null || element.dataset == null)
                return;

            for (var key in DependencyProperty.DependencyProperties) {
                var dpDataset = element.dataset[key];

                if (dpDataset != null) {
                    var dp = DependencyProperty.DependencyProperties[key];

                    var markupExtensionObj = this.getMarkupExtensionObject(dpDataset);

                    if (markupExtensionObj != null) {
                        var htmlService = new HtmlServiceProvider();
                        htmlService.TargetProperty = dp;
                        htmlService.TargetObject = element;
                        var value = markupExtensionObj.provideValue(htmlService);

                        if (value instanceof BindingExpressionBase) {
                            var bindExpr = value;
                            element[key + 'Expression'] = bindExpr;
                            bindExpr.UpdateTarget();
                        } else {
                            element[key] = value;
                        }
                    }
                }
            }
        };

        HtmlMarkup.getMarkupExtensionObject = function (markupString) {
            if (markupString != null) {
                var bindingPattern = new RegExp("{(.*)}");

                if (bindingPattern.test(markupString) == false) {
                    return null;
                }

                var extractedString = bindingPattern.exec(markupString)[1];
                var spaceAt = extractedString.indexOf(' ', 0);
                var markupExtension = extractedString.substr(0, spaceAt);

                var markupExtensionObj = Object.create(MarkupExtension.MarkupExtensions[markupExtension]);
                markupExtensionObj.constructor.apply();

                //build new object
                markupExtensionObj.name = markupExtension;

                //extract parameter string array
                var extsParams = extractedString.substr(spaceAt + 1).split(',');

                for (var i = 0; i < extsParams.length; i++) {
                    var splittedParams = extsParams[i].split('=');

                    if (splittedParams.length == 1) {
                        markupExtensionObj[anonymousProperty + '_' + i] = splittedParams[0];
                    } else {
                        markupExtensionObj[splittedParams[0]] = splittedParams[1];
                    }
                }
                return markupExtensionObj;
            }
            return null;
        };
        return HtmlMarkup;
    })();
    ao.HtmlMarkup = HtmlMarkup;

    var EventArg = (function () {
        function EventArg() {
        }
        return EventArg;
    })();
    ao.EventArg = EventArg;

    var ChangedEvent = (function () {
        function ChangedEvent() {
            this.listeners = [];
            this.listeners = [];
        }
        ChangedEvent.prototype.addEvent = function (listener) {
            if (listener == null)
                return;

            this.listeners.push(listener);
        };

        ChangedEvent.prototype.removeEvent = function (listener) {
            if (listener == null || this.listeners == null)
                return;

            var index = this.listeners.indexOf(listener);
            if (index >= 0) {
                this.listeners.splice(index, 1);
            }
        };

        ChangedEvent.prototype.dispatch = function (sender, eventArg) {
            if (this.listeners == null)
                return false;

            var hasBeenCanceled = this.listeners.every(function (listener) {
                var result = listener(sender, eventArg);
                return result !== false;
            });

            return hasBeenCanceled;
        };
        ChangedEvent.prototype.clear = function () {
            this.listeners = [];
        };
        return ChangedEvent;
    })();
    ao.ChangedEvent = ChangedEvent;
})(ao || (ao = {}));

ao.DependencyProperty.DependencyProperties = {};
ao.MarkupExtension.MarkupExtensions = {};

ao.MarkupExtension.register("binding", ao.Binding.prototype);
ao.MarkupExtension.register("staticResource", ao.StaticResourceExtension.prototype);
ao.MarkupExtension.register("dynamicResource", ao.DynamicResourceExtension.prototype);
ao.MarkupExtension.register("relativeSource", ao.RelativeSourceExtension.prototype);

HTMLElement.prototype.onChangeNotify = new ao.ChangedEvent();

Object.prototype.onChangeNotify = new ao.ChangedEvent();

HTMLElement.prototype.setValue = function (dp, value) {
    var propertyChangedCallback = dp.DefaultMetadata.GetPropertyChangedCallback;
    if (propertyChangedCallback != null) {
        var oldValue = _this.getValue(dp);
        propertyChangedCallback(_this, new ao.DependencyPropertyChangedEventArgs(dp, oldValue, value));
    }
    _this[dp.Name] = value;
};

HTMLElement.prototype.getValue = function (dp) {
    return _this[dp.Name];
};

HTMLElement.prototype.clearValue = function (dp) {
    _this[dp.Name] = null;
};

function DataContextPropertyChangedCallback(d, e) {
    var element = d;
    element['dataContext'] = e.newValue;
    element.onChangeNotify.dispatch(element, e.newValue);

    var changeNotify = function (sender, evenArgs) {
        if (sender != element) {
            element.onChangeNotify.dispatch(element, e.newValue);
        }
    };

    if (e.newValue != null) {
        e.newValue.onChangeNotify.addEvent(changeNotify);
    }
    if (e.oldValue != null) {
        e.onChangeNotify.removeEvent(changeNotify);
    }
}

function onChangeNotify(sender, e) {
}

function DataContextCoerceValueCallback(d, baseValue) {
    var element = d;
}

var DataContextPropertyMetadata = new ao.PropertyMetadata(null, DataContextPropertyChangedCallback, DataContextCoerceValueCallback);

HTMLElement.prototype.DataContextProperty = ao.DependencyProperty.Register("dataContext", Object.prototype, HTMLElement.prototype, DataContextPropertyMetadata, null);

function TextPropertyChangedCallback(d, e) {
    var element = d;
    if (element.nodeName == "LABEL" || element.nodeName == "DIV" || element.nodeName == "SPAN") {
        element.innerHTML = e.newValue;
    } else if (element.nodeName == "INPUT") {
        element.value = e.newValue;
    }
}

function TextCoerceValueCallback(d, baseValue) {
    var inputElement = d;
}

var TextPropertyMetadata = new ao.PropertyMetadata("", TextPropertyChangedCallback, TextCoerceValueCallback);

HTMLInputElement.prototype.TextProperty = ao.DependencyProperty.Register("text", String.prototype, HTMLInputElement.prototype, TextPropertyMetadata, null);

//---------------------
//Apply binding onload
window.addEventListener("load", function (ev) {
    ao.HtmlMarkup.bind();
});
//# sourceMappingURL=ActiveObject.js.map
